package team.fhhm.bigwebhomeworkservert.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import team.fhhm.bigwebhomeworkservert.model.Employee;
import team.fhhm.bigwebhomeworkservert.model.Leave;
import team.fhhm.bigwebhomeworkservert.repo.EmployeeRepository;
import team.fhhm.bigwebhomeworkservert.repo.LeaveRepository;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api")

public class LeaveController {

    @Autowired
    LeaveRepository lrepository;
    @Autowired
    EmployeeRepository erepository;

    @PostMapping("/leaves/create")
    public ResponseEntity<String> createLeave(@RequestBody Leave leave) {
    	
    	List<Leave> leaves = new ArrayList<Leave>();
    	lrepository.findByEmployeeOrderBySubmitDescStarttimeAscEndtimeAsc(leave.getEmployee()).forEach(leaves::add);
    	for (int i = 0; i < leaves.size(); i ++) {
    		if (leave.getStarttime().compareTo(leaves.get(i).getStarttime()) == 0)
    			return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    		else if (leave.getStarttime().before(leaves.get(i).getStarttime())) {
    			if (leave.getEndtime().after(leaves.get(i).getStarttime()))
    				return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    		}
    		else {
    			if (leaves.get(i).getEndtime().after(leave.getStarttime())) {
    				return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    			}
    		}
    	}
    	lrepository.save(leave);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @GetMapping("/leaves/mine/{eid}")
    public List<Leave> getMyLeave(@PathVariable("eid") String eid) {
    	
    	Optional<Employee> employeeData = erepository.findById(eid);
    	if (employeeData.isPresent()) {
    		Employee employee = employeeData.get();
    		List<Leave> leaves = new ArrayList<Leave>();
    		lrepository.findByEmployeeOrderBySubmitDescStarttimeAscEndtimeAsc(employee).forEach(leaves::add);
    		return leaves;
    	}
    	return null;
    }
    
    @GetMapping("/leaves/unhandled/{eid}")
    public List<Leave> getMyUnhandledLeave(@PathVariable("eid") String eid) {
    	
    	Optional<Employee> employeeData = erepository.findById(eid);
    	if (employeeData.isPresent()) {
    		Employee employee = employeeData.get();
    		List<Leave> leaves = new ArrayList<Leave>();
    		lrepository.findByEmployeeAndStateOrderBySubmitDescStarttimeAscEndtimeAsc(employee, 0).forEach(leaves::add);
    		return leaves;
    	}
    	return null;
    }
    
    @GetMapping("/leaves/passed/{eid}")
    public List<Leave> getMyPassedLeave(@PathVariable("eid") String eid) {
    	
    	Optional<Employee> employeeData = erepository.findById(eid);
    	if (employeeData.isPresent()) {
    		Employee employee = employeeData.get();
    		List<Leave> leaves = new ArrayList<Leave>();
    		lrepository.findByEmployeeAndStateOrderBySubmitDescStarttimeAscEndtimeAsc(employee, 1).forEach(leaves::add);
    		return leaves;
    	}
    	return null;
    }
    
    @GetMapping("/leaves/unpassed/{eid}")
    public List<Leave> getMyUnpassedLeave(@PathVariable("eid") String eid) {
    	
    	Optional<Employee> employeeData = erepository.findById(eid);
    	if (employeeData.isPresent()) {
    		Employee employee = employeeData.get();
    		List<Leave> leaves = new ArrayList<Leave>();
    		lrepository.findByEmployeeAndStateOrderBySubmitDescStarttimeAscEndtimeAsc(employee, 2).forEach(leaves::add);
    		return leaves;
    	}
    	return null;
    }
    
    @GetMapping("/leaves/absent")
    public List<Leave> getAbsentEmployee() {
    	
    	List<Leave> leaves = new ArrayList<Leave>();
    	lrepository.findByState(1).forEach(leaves::add);
    	Date now = new Date();
    	List<Leave> result = new ArrayList<Leave>();
    	for (int i = 0; i < leaves.size(); i ++) {
    		if ((!leaves.get(i).getStarttime().after(now)) && leaves.get(i).getEndtime().after(now))
    			result.add(leaves.get(i));
    	}
    	return result;
    }

    @GetMapping("/leaves/all")
    public List<Leave> getAllLeave() {

        List<Leave> leaves = new ArrayList<Leave>();
        lrepository.findAllByOrderBySubmitDescStarttimeAscEndtimeAsc().forEach(leaves::add);
        return leaves;
    }

    @GetMapping("/leaves/prehandled/{eid}")
    public List<Leave> getUnhandled(@PathVariable("eid") String eid) {

    	Optional<Employee> employeeData = erepository.findById(eid);
    	if (employeeData.isPresent()) {
    		Employee employee = employeeData.get();
    		List<Leave> leaves = new ArrayList<Leave>();
            lrepository.findByStateAndGrade(0, employee.getAuthority()).forEach(leaves::add);
            return leaves;
    	}
    	return null;
    }

    @PutMapping("/leaves/pass/{lid}")
    public ResponseEntity<String> passLeave(@PathVariable("lid") int lid) {

        Optional<Leave> leaveData = lrepository.findById(lid);
        if (leaveData.isPresent()) {
        	Leave leave = leaveData.get();
        	Optional<Employee> employeeData = erepository.findById(leave.getEmployee().getEid());
        	if (employeeData.isPresent()) {
        		Employee employee = employeeData.get();
        		int between = (int)((leave.getEndtime().getTime() - leave.getStarttime().getTime()) / (1000 * 60 * 60 * 24));
        		if (leave.getType() == 5) {
            		if (employee.getAnnualleave() >= between) {
            			if (leave.getGrade() == 1) {
                    		if (between == 1)
                    			leave.setState(1);
                    		else
                    			leave.setGrade(2);
                    	}
                    	else if (leave.getGrade() == 2) {
                    		if (between <= 3)
                    			leave.setState(1);
                    		else
                    			leave.setGrade(3);
                    	}
                    	else if (leave.getGrade() == 3)
                    		leave.setState(1);
                    	else
                    		return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            			if (leave.getState() == 1)
            				employee.setAnnualleave(employee.getAnnualleave() - between);
            			lrepository.deleteById(lid);
            			lrepository.save(leave);
            			return new ResponseEntity<>(HttpStatus.OK);
            		}
            		return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        		}
        		else {
        			if (leave.getGrade() == 1) {
                		if (between == 1)
                			leave.setState(1);
                		else
                			leave.setGrade(2);
                	}
                	else if (leave.getGrade() == 2) {
                		if (between <= 3)
                			leave.setState(1);
                		else
                			leave.setGrade(3);
                	}
                	else if (leave.getGrade() == 3)
                		leave.setState(1);
                	else
                		return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        			lrepository.deleteById(lid);
        			lrepository.save(leave);
        			return new ResponseEntity<>(HttpStatus.OK);
        		}
        	}
        	return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    
    @PutMapping("/leaves/unpass/{lid}")
    public ResponseEntity<String> unpassLeave(@PathVariable("lid") int lid, @RequestBody Leave leave) {

        Optional<Leave> leaveData = lrepository.findById(lid);
        if (leaveData.isPresent()) {
        	leave.setState(2);
        	lrepository.deleteById(lid);
        	lrepository.save(leave);
            return new ResponseEntity<>(HttpStatus.OK);
        }
        else
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    
    @PutMapping(value = "/leaves/update/{lid}")
    public ResponseEntity<String> updateLeave(@PathVariable("lid") int lid, @RequestBody Leave leave) {

    	Optional<Leave> leaveData = lrepository.findById(lid);
        if (leaveData.isPresent()) {
        	List<Leave> leaves = new ArrayList<Leave>();
        	lrepository.findByEmployeeOrderBySubmitDescStarttimeAscEndtimeAsc(leave.getEmployee()).forEach(leaves::add);
        	for (int i = 0; i < leaves.size(); i ++) {
        		if (leaves.get(i).getLid() != lid) {
        			if (leave.getStarttime().compareTo(leaves.get(i).getStarttime()) == 0)
            			return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            		else if (leave.getStarttime().before(leaves.get(i).getStarttime())) {
            			if (leave.getEndtime().after(leaves.get(i).getStarttime()))
            				return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            		}
            		else {
            			if (leaves.get(i).getEndtime().after(leave.getStarttime())) {
            				return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            			}
            		}
        		}
        	}
        	lrepository.deleteById(lid);
        	lrepository.save(leave);
            return new ResponseEntity<>(HttpStatus.OK);
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }

    @DeleteMapping("/leaves/delete/{lid}")
    public ResponseEntity<String> deleteLeave(@PathVariable("lid") int lid) {
    	
    	Optional<Leave> leaveData = lrepository.findById(lid);
    	if (leaveData.isPresent()) {
    		lrepository.deleteById(lid);
            return new ResponseEntity<>(HttpStatus.OK);
    	}
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
}